package services

import (
	"context"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/ptypes/wrappers"
	"github.com/micro/go-micro/v2/client"

	context2 "kop/framework/context"
	"kop/pb"
	"kop/pb/service"

	conquerC "kop/modules/conquer/client"
	maidC "kop/modules/maid/client"
	moneyC "kop/modules/money/client"
	rankingC "kop/modules/ranking/client"
	roleC "kop/modules/role/client"
	stageC "kop/modules/stage/client"
	wBossC "kop/modules/world_boss/client"
)

type RankingService struct {
	context2.Context
}

func (s *RankingService) Ranking(ctx context.Context, req *pb.RankingRequest) (*pb.RankingResp, error) {

	var roleID, serverID = s.GetRoleID(ctx), s.GetServerID(ctx)
	var reply pb.RankingResp

	switch req.Type {

	case pb.RankingType_RankingIncome:

		reply.Ranking = s.ServerRanking(serverID, moneyC.MoneyService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = moneyC.MoneyService.MyRanking(ctx, &empty.Empty{})
		}

		reply.Ok = rankingC.IsWorship(ctx, 1)

	case pb.RankingType_RankingPower:

		reply.Ranking = s.ServerRanking(serverID, roleC.RoleService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = roleC.RoleService.MyRanking(ctx, &empty.Empty{})
		}

		reply.Ok = rankingC.IsWorship(ctx, 2)

	case pb.RankingType_RankingStage:

		reply.Ranking = s.ServerRanking(serverID, stageC.StageService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = stageC.StageService.MyRanking(ctx, &empty.Empty{})
		}

		reply.Ok = rankingC.IsWorship(ctx, 3)

	case pb.RankingType_RankingIntimacy:

		reply.Ranking = s.ServerRanking(serverID, maidC.MaidService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = maidC.MaidService.MyRanking(ctx, &empty.Empty{})
		}

		reply.Ok = rankingC.IsWorship(ctx, 4)

	case pb.RankingType_RankingPopularity:

		reply.Ranking = s.ServerRanking(serverID, rankingC.RankingService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			var res, err = rankingC.RankingService.MyRanking(ctx, &empty.Empty{})
			if err == nil && res.Number != 0 {
				reply.MyRanking = res
			}
		}

	case pb.RankingType_RankingConquer:

		reply.Ranking = s.ServerRanking(serverID, conquerC.ConquerService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = conquerC.ConquerService.MyRanking(ctx, &empty.Empty{})
		}

	case pb.RankingType_RankingWorldBoss:

		reply.Ranking = s.ServerRanking(s.GetServerID(ctx), wBossC.WorldBossService)
		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = wBossC.WorldBossService.MyRanking(ctx, &empty.Empty{})
		}

	case pb.RankingType_RankingWorldBossKill:

		var res, err = wBossC.WorldBossService.KillRanking(context.Background(), &wrappers.Int32Value{})
		if err != nil {
			return &reply, err
		}

		var roleIDs = make([]int32, 0, len(res.Ranking))
		for _, v := range res.Ranking {
			roleIDs = append(roleIDs, v.RoleID)
		}

		var roles = roleC.GetRoles(roleIDs)

		reply.Ranking = make([]*pb.Ranking, 0, len(res.Ranking))
		for k, v := range res.Ranking {

			reply.Ranking = append(reply.Ranking, &pb.Ranking{
				Role:   roles[v.RoleID],
				Number: int32(k) + 1,
				Points: v.Points,
			})
		}

		s.findRole(&reply, roleID)

		if reply.MyRanking == nil {
			reply.MyRanking, _ = wBossC.WorldBossService.MyKillRanking(ctx, &empty.Empty{})
		}

	case pb.RankingType_RankingWorldBossDamage:

		var res, err = wBossC.WorldBossService.DamageRanking(ctx, &empty.Empty{})
		if err != nil {
			return &reply, err
		}

		var roleIDs = make([]int32, 0, len(res.Ranking))
		for _, v := range res.Ranking {
			roleIDs = append(roleIDs, v.RoleID)
		}

		var roles = roleC.GetRoles(roleIDs)

		reply.Ranking = make([]*pb.Ranking, 0, len(res.Ranking))
		for k, v := range res.Ranking {

			reply.Ranking = append(reply.Ranking, &pb.Ranking{
				Role:   roles[v.RoleID],
				Number: int32(k) + 1,
				Points: v.Points,
			})
		}

		reply.MyRanking = res.Number
	}

	//if req.Page == 1 {
	//	// 第一页 补上我的积分
	//	switch req.Type {
	//	case pb.RankingType_RankingConquer:
	//
	//		reply.MyRanking, err = conquerC.ConquerService.MyRankingNumber(context.Background(), &service.DefaultRequest{RoleID: s.GetRoleID(ctx), Value: s.GetServerID(ctx)})
	//		if err != nil {
	//			return &reply, err
	//		}
	//
	//	case pb.RankingType_RankingWorldBoss:
	//
	//		reply.MyRanking, err = wBoss.WorldBossService.MyRankingNumber(context.Background(), &service.DefaultRequest{RoleID: s.GetRoleID(ctx), Value: s.GetServerID(ctx)})
	//		if err != nil {
	//			return &reply, err
	//		}
	//
	//	case pb.RankingType_RankingWorldBossKill:
	//
	//		reply.MyRanking, err = wBoss.WorldBossService.MyKillNumber(context.Background(), &service.DefaultRequest{RoleID: s.GetRoleID(ctx), Value: s.GetServerID(ctx)})
	//		if err != nil {
	//			return &reply, err
	//		}
	//	}
	//}

	return &reply, nil
}

func (*RankingService) Kings(ctx context.Context, req *empty.Empty) (*pb.KingsResp, error) {

	return rankingC.RankingService.Kings(ctx, req)
}
func (*RankingService) GetKing(ctx context.Context, req *wrappers.Int32Value) (*pb.GetKingResp, error) {

	return rankingC.RankingService.GetKing(ctx, req)
}
func (*RankingService) UseRing(ctx context.Context, req *wrappers.Int32Value) (*pb.Item, error) {

	return rankingC.RankingService.UseRing(ctx, req)
}
func (*RankingService) WorshipKing(ctx context.Context, req *wrappers.Int32Value) (*pb.AwardItem, error) {

	return rankingC.RankingService.WorshipKing(ctx, req)
}
func (*RankingService) WorshipRanking(ctx context.Context, req *wrappers.Int32Value) (*pb.AwardItem, error) {

	return rankingC.RankingService.WorshipRanking(ctx, req)
}

type Interface interface {
	Ranking(context.Context, *wrappers.Int32Value, ...client.CallOption) (*service.RankingPointsList, error)
}

func (s *RankingService) ServerRanking(serverID int32, srv Interface) []*pb.Ranking {

	var res, err = srv.Ranking(context.Background(), &wrappers.Int32Value{Value: serverID})
	if err != nil {
		panic(err)
	}

	var roleIDs = make([]int32, 0, len(res.Ranking))
	for _, v := range res.Ranking {
		roleIDs = append(roleIDs, v.RoleID)
	}

	var roles = roleC.GetRoles(roleIDs)

	var arr = make([]*pb.Ranking, 0, len(res.Ranking))
	for k, v := range res.Ranking {

		arr = append(arr, &pb.Ranking{
			Role:   roles[v.RoleID],
			Number: int32(k) + 1,
			Points: v.Points,
		})
	}
	return arr
}

func (s *RankingService) findRole(resp *pb.RankingResp, roleID int32) {

	for k, v := range resp.Ranking {
		if v.Role.RoleID == roleID {

			resp.MyRanking = &pb.RankingNumber{
				Number: int32(k) + 1,
				Points: v.Points,
			}
		}
	}
}
